package org.finesys.common.excel.handler;

import cn.idev.excel.context.AnalysisContext;
import lombok.extern.slf4j.Slf4j;
import org.finesys.common.excel.annotaion.ExcelLine;
import org.finesys.common.excel.exception.ErrorMessage;
import org.finesys.common.excel.util.Validators;

import javax.validation.ConstraintViolation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
public class DefaultAnalysisEventListener extends ListAnalysisEventListener<Object> {

    private final List<Object> list = new ArrayList<>();
    private final List<ErrorMessage> errorMessageList = new ArrayList<>();
    private Long lineNum = 1L;

    /**
     * 一行行读取方法回调
     */
    @Override
    public void invoke(Object o, AnalysisContext analysisContext) {
        lineNum++;
        Set<ConstraintViolation<Object>> violationSet = Validators.validate(o);
        if (!violationSet.isEmpty()) {
            Set<String> messageSet = violationSet.stream().map(ConstraintViolation::getMessage).collect(Collectors.toSet());
            errorMessageList.add(new ErrorMessage(lineNum, messageSet));
        } else {
            Field[] fields = o.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(ExcelLine.class) && field.getType() == Long.class) {
                    try {
                        field.setAccessible(true);
                        field.set(o, lineNum);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
            list.add(o);
        }
    }

    /**
     * 读取完成后调用方法
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (log.isDebugEnabled()) {
            log.debug("Excel read Analysed");
        }
    }

    @Override
    public List<ErrorMessage> getErrors() {
        return errorMessageList;
    }

    @Override
    public List<Object> getList() {
        return list;
    }
}
